﻿using DimensionsHelper.Common.Contracts.TableFormatter.Options;
using DimensionsHelper.Common.TableFormatter;
using Microsoft.UI.Text;
using Windows.UI.Text;

namespace DimensionsHelper.Client.WinUi.ViewModels;

public partial class TableFormatterTableOptionsViewModel : ObservableRecipient
{
    private static readonly string[] RangeLocationLabels;


    static TableFormatterTableOptionsViewModel()
    {
        RangeLocationLabels = TypeHelper.ReadEnumMembersDescription<TableRangeLocations>().Keys.ToArray();
    }

    public TableFormatterTableOptionsViewModel()
    {
        GlobalStyle = new ExcelRangeStyleViewModel();
        HeaderStyle = new ExcelRangeStyleViewModel();
        TitleStyle = new ExcelRangeStyleViewModel();
        SectionStyle = new ExcelRangeStyleViewModel();
        SectionMemberStyle = new ExcelRangeStyleViewModel();
        SideStyle = new ExcelRangeStyleViewModel();
        InnerTextStyle = new ExcelRangeStyleViewModel();
        DataStyle = new ExcelRangeStyleViewModel();
        BaseLabelStyle = new ExcelRangeStyleViewModel();
        BaseValueStyle = new ExcelRangeStyleViewModel();
        HyperlinkStyle = new ExcelRangeStyleViewModel();
        SigColumCharacterStyle = new ExcelRangeStyleViewModel();
        SigResultStyle = new ExcelRangeStyleViewModel();
        LowerCaseSigCharacterStyle = new ExcelRangeStyleViewModel();
        UpperCaseSigCharacterStyle = new ExcelRangeStyleViewModel();

        MenuGlobalStyle = new ExcelRangeStyleViewModel();
        MenuLinkSheetGlobalStyle = new ExcelRangeStyleViewModel();
        MenuLinkSheetLabelStyle = new ExcelRangeStyleViewModel();
        MenuLinkSheetSheetNameStyle = new ExcelRangeStyleViewModel();
        MenuBackTextStyle = new ExcelRangeStyleViewModel();
        MenuTableNumberStyle = new ExcelRangeStyleViewModel();
        MenuSectionStyle = new ExcelRangeStyleViewModel();
        MenuBaseLabelStyle = new ExcelRangeStyleViewModel();
        MenuSheetLabelStyle = new ExcelRangeStyleViewModel();
        MenuTableLabelStyle = new ExcelRangeStyleViewModel();

        Ranges = new ExcelRangeStyleViewModel[(int)TableRangeLocations.StylesCount];
        Ranges[(int)TableRangeLocations.Section] = SectionStyle;
        Ranges[(int)TableRangeLocations.Header] = HeaderStyle;
        Ranges[(int)TableRangeLocations.SectionMember] = SectionMemberStyle;
        Ranges[(int)TableRangeLocations.Title] = TitleStyle;
        Ranges[(int)TableRangeLocations.BaseLabel] = BaseLabelStyle;
        Ranges[(int)TableRangeLocations.BaseValue] = BaseValueStyle;
        Ranges[(int)TableRangeLocations.Side] = SideStyle;
        Ranges[(int)TableRangeLocations.InnerText] = InnerTextStyle;
        Ranges[(int)TableRangeLocations.Data] = DataStyle;
        Ranges[(int)TableRangeLocations.SigColumnCharacter] = SigColumCharacterStyle;
        Ranges[(int)TableRangeLocations.SigResult] = SigResultStyle;
        Ranges[(int)TableRangeLocations.Global] = GlobalStyle;
        Ranges[(int)TableRangeLocations.Hyperlink] = HyperlinkStyle;
        Ranges[(int)TableRangeLocations.LowerCaseSigCharacter] = LowerCaseSigCharacterStyle;
        Ranges[(int)TableRangeLocations.UpperCaseSigCharacter] = UpperCaseSigCharacterStyle;
        // MenuRanges
        Ranges[(int)TableRangeLocations.MenuLinkSheetGobal] = MenuLinkSheetGlobalStyle;
        Ranges[(int)TableRangeLocations.MenuGlobal] = MenuGlobalStyle;
        Ranges[(int)TableRangeLocations.MenuLinkSheetLabel] = MenuLinkSheetLabelStyle;
        Ranges[(int)TableRangeLocations.MenuLinkSheetSheetName] = MenuLinkSheetSheetNameStyle;
        Ranges[(int)TableRangeLocations.MenuBackText] = MenuBackTextStyle;
        Ranges[(int)TableRangeLocations.MenuTableNumber] = MenuTableNumberStyle;
        Ranges[(int)TableRangeLocations.MenuSection] = MenuSectionStyle;
        Ranges[(int)TableRangeLocations.MenuBaseLabel] = MenuBaseLabelStyle;
        Ranges[(int)TableRangeLocations.MenuSheetLabel] = MenuSheetLabelStyle;
        Ranges[(int)TableRangeLocations.MenuTableLabel] = MenuTableLabelStyle;

        IsFontOptionsEnabled = true;
        MenuLinkSheetLabel = TableFormatterDefaultValues.MenuLinkSheetLabel;
        MenuBackText = TableFormatterDefaultValues.MenuBackText;
        MenuLinkSheetName = TableFormatterDefaultValues.MenuLinkSheetName;
        MenuIndexSheetName = TableFormatterDefaultValues.MenuIndexSheetName;
        MenuBaseContentFormat = TableFormatterDefaultValues.BaseContentFormat;

        MenuSheetLabelTextBindingStyle = MenuSheetLabelStyle;
        MenuTableLabelTextBindingStyle = MenuTableLabelStyle;

        SetCurrentStyleRange(TableRangeLocations.Global);
        GlobalStyle.PropertyChanged += OnGlobalOptionPropertyChanged;
        MenuLinkSheetGlobalStyle.PropertyChanged += OnMenuLinkSheetGlobalOptionPropertyChanged;
        MenuGlobalStyle.PropertyChanged += OnMenuGlobalOptionPropertyChanged;
        HyperlinkStyle.PropertyChanged += OnHyperlinkOptionPropertyChanged;
        TitleStyle.PropertyChanged += OnTitleStyleOptionPropertyChanged;

        SigComparisons = [];
    }


    private bool UpdatingInternal { get; set; }


    private ExcelRangeStyleViewModel[] Ranges
    {
        get;
    }


    [ObservableProperty]
    public partial string CurrentStyleLabel { get; set; }


    [ObservableProperty]
    public partial bool IsRangeOptionsEnabled { get; set; }


    [ObservableProperty]
    public partial bool IsFontOptionsEnabled { get; set; }


    [ObservableProperty]
    public partial ExcelRangeStyleViewModel CurrentStyle { get; set; }


    [ObservableProperty]
    public partial FontWeight TitleFontWeight { get; set; }


    public ExcelRangeStyleViewModel GlobalStyle
    {
        get;
    }


    public ExcelRangeStyleViewModel HeaderStyle
    {
        get;
    }


    public ExcelRangeStyleViewModel TitleStyle
    {
        get;
    }


    public ExcelRangeStyleViewModel HyperlinkStyle
    {
        get;
    }


    public ExcelRangeStyleViewModel SideStyle
    {
        get;
    }


    public ExcelRangeStyleViewModel InnerTextStyle
    {
        get;
    }


    public ExcelRangeStyleViewModel SectionStyle
    {
        get;
    }


    public ExcelRangeStyleViewModel SectionMemberStyle
    {
        get;
    }


    public ExcelRangeStyleViewModel DataStyle
    {
        get;
    }


    public ExcelRangeStyleViewModel BaseLabelStyle
    {
        get;
    }


    public ExcelRangeStyleViewModel BaseValueStyle
    {
        get;
    }


    public ExcelRangeStyleViewModel SigColumCharacterStyle
    {
        get;
    }


    public ExcelRangeStyleViewModel SigResultStyle
    {
        get;
    }


    public ExcelRangeStyleViewModel LowerCaseSigCharacterStyle
    {
        get;
    }


    public ExcelRangeStyleViewModel UpperCaseSigCharacterStyle
    {
        get;
    }


    public ExcelRangeStyleViewModel MenuLinkSheetGlobalStyle
    {
        get;
    }


    public ExcelRangeStyleViewModel MenuGlobalStyle
    {
        get;
    }


    [ObservableProperty]
    public partial int IntervalRows { get; set; }


    [ObservableProperty]
    public partial string TitleFeature { get; set; } = TableFormatterDefaultValues.TableTitleFeature;


    [ObservableProperty]
    public partial string DisplayTitleFeature { get; set; } = TableFormatterDefaultValues.TableTitleFeature;


    [ObservableProperty]
    public partial int TitleOffset { get; set; }


    [ObservableProperty]
    public partial string TableEndFeature { get; set; } = TableFormatterDefaultValues.TableEndFeature;


    [ObservableProperty]
    public partial bool HideTitleFeature { get; set; }


    [ObservableProperty]
    public partial string BaseFeature { get; set; } = TableFormatterDefaultValues.BaseFeature;


    [ObservableProperty]
    public partial bool CorrectTableNumber { get; set; }


    [ObservableProperty]
    public partial double FirstColumnWidth { get; set; } = TableFormatterDefaultValues.TableFirstColumnWidth;


    [ObservableProperty]
    public partial double FixedColumnWidth { get; set; } = TableFormatterDefaultValues.TableFixedColumnWidth;


    [ObservableProperty]
    public partial bool MergeTopLeftCell { get; set; }


    [ObservableProperty]
    public partial bool MergeHeader { get; set; }


    [ObservableProperty]
    public partial bool MergeHeaderEmptyRows { get; set; }


    [ObservableProperty]
    public partial bool ReadSection { get; set; }


    [ObservableProperty]
    public partial bool ShowSection { get; set; }


    [ObservableProperty]
    public partial bool RemoveHeaderEmptyRows { get; set; }


    [ObservableProperty]
    public partial bool RemoveHeaderSpec { get; set; }


    [ObservableProperty]
    public partial bool RemoveTailSpec { get; set; }


    [ObservableProperty]
    public partial string SectionFeatureText { get; set; } = "[]";


    [ObservableProperty]
    public partial string SectionStartFeature { get; set; } = "[";


    [ObservableProperty]
    public partial string SectionEndFeature { get; set; } = "]";


    [ObservableProperty]
    public partial string DisplaySectionStartFeature { get; set; } = "[";


    [ObservableProperty]
    public partial string DisplaySectionEndFeature { get; set; } = "]";


    [ObservableProperty]
    public partial string DisplayTitleSection { get; set; } = "Section";


    [ObservableProperty]
    public partial string TableNumberFeature { get; set; } = TableFormatterDefaultValues.TableNumberFeature;


    [ObservableProperty]
    public partial string TableNumberFormat { get; set; } = TableFormatterDefaultValues.TableNumberFormat;


    [ObservableProperty]
    public partial bool MergeSig { get; set; }


    [ObservableProperty]
    public partial bool SideColorIgnoreEmpty { get; set; }


    [ObservableProperty]
    public partial int MaxEmptyRows { get; set; }


    // Menu

    public ExcelRangeStyleViewModel MenuLinkSheetLabelStyle
    {
        get;
    }


    public ExcelRangeStyleViewModel MenuLinkSheetSheetNameStyle
    {
        get;
    }


    public ExcelRangeStyleViewModel MenuBackTextStyle
    {
        get;
    }


    public ExcelRangeStyleViewModel MenuTableNumberStyle
    {
        get;
    }


    public ExcelRangeStyleViewModel MenuSectionStyle
    {
        get;
    }


    public ExcelRangeStyleViewModel MenuSheetLabelStyle
    {
        get;
    }


    public ExcelRangeStyleViewModel MenuBaseLabelStyle
    {
        get;
    }


    public ExcelRangeStyleViewModel MenuTableLabelStyle
    {
        get;
    }


    [ObservableProperty]
    public partial ExcelRangeStyleViewModel MenuSheetLabelTextBindingStyle { get; set; }


    [ObservableProperty]
    public partial ExcelRangeStyleViewModel MenuTableLabelTextBindingStyle { get; set; }


    [ObservableProperty]
    public partial string MenuLinkSheetName { get; set; }


    [ObservableProperty]
    public partial string MenuIndexSheetName { get; set; }


    [ObservableProperty]
    public partial string MenuLinkSheetLabel { get; set; }


    [ObservableProperty]
    public partial bool BuildMenu { get; set; }


    [ObservableProperty]
    public partial string MenuBackText { get; set; }


    [ObservableProperty]
    public partial bool ShowMenuBase { get; set; }


    [ObservableProperty]
    public partial bool ShowMenuSection { get; set; }


    [ObservableProperty]
    public partial bool IsMenuSectionMerged { get; set; }


    [ObservableProperty]
    public partial bool IsMenuNumberHidden { get; set; }


    [ObservableProperty]
    public partial string MenuBaseContentFormat { get; set; }


    [ObservableProperty]
    public partial bool ShowMenuMultiBase { get; set; }


    [ObservableProperty]
    public partial bool ShowMultiBaseInOneCell { get; set; }


    [ObservableProperty]
    public partial bool HideSigResultCharacter { get; set; }


    [ObservableProperty]
    public partial bool HideSigColumnCharacter { get; set; }


    [ObservableProperty]
    public partial double SigBoundary { get; set; }


    [ObservableProperty]
    public partial SigGapBoundaryType SigBoundaryType { get; set; }


    public SigComparisonMapViewModel SigComparisons
    {
        get;
    }


    private void SetRangesPropertyValue<T>(Action<ExcelRangeStyleViewModel, T> setter, T value,
        TableRangeLocations startLoc, TableRangeLocations endLoc)
    {
        for (int i = (int)startLoc; i < (int)endLoc; i++)
        {
            setter(Ranges[i], value);
        }
    }


    private void UpdateRangePropertyByCallback(string? propertyName, ExcelRangeStyleViewModel sourceStyle,
        TableRangeLocations startLoc, TableRangeLocations endLoc)
    {
        switch (propertyName)
        {
            case nameof(ExcelRangeStyleViewModel.Bold):
            {
                SetRangesPropertyValue(static (r, v) => r.Bold = v, sourceStyle.Bold, startLoc, endLoc);
                break;
            }

            case nameof(ExcelRangeStyleViewModel.Italic):
            {
                SetRangesPropertyValue(static (r, v) => r.Italic = v, sourceStyle.Italic, startLoc, endLoc);
                break;
            }

            case nameof(ExcelRangeStyleViewModel.Underlined):
            {
                SetRangesPropertyValue(static (r, v) => r.Underlined = v, sourceStyle.Underlined, startLoc, endLoc);
                break;
            }

            case nameof(ExcelRangeStyleViewModel.FontFamily):
            {
                SetRangesPropertyValue(static (r, v) => r.FontFamily = v, sourceStyle.FontFamily, startLoc, endLoc);
                break;
            }

            case nameof(ExcelRangeStyleViewModel.FontSize):
            {
                SetRangesPropertyValue(static (r, v) => r.FontSize = v, sourceStyle.FontSize, startLoc, endLoc);
                break;
            }

            case nameof(ExcelRangeStyleViewModel.FontColor):
            {
                SetRangesPropertyValue(static (r, v) => r.FontColor = v, sourceStyle.FontColor, startLoc, endLoc);
                break;
            }

            case nameof(ExcelRangeStyleViewModel.InteriorColor):
            {
                SetRangesPropertyValue(static (r, v) => r.InteriorColor = v, sourceStyle.InteriorColor, startLoc,
                    endLoc);
                break;
            }

            case nameof(ExcelRangeStyleViewModel.HAlignLeft):
            {
                SetRangesPropertyValue(static (r, v) => r.HAlignLeft = v, sourceStyle.HAlignLeft, startLoc, endLoc);
                break;
            }

            case nameof(ExcelRangeStyleViewModel.HAlignCenter):
            {
                SetRangesPropertyValue(static (r, v) => r.HAlignCenter = v, sourceStyle.HAlignCenter, startLoc, endLoc);
                break;
            }

            case nameof(ExcelRangeStyleViewModel.HAlignRight):
            {
                SetRangesPropertyValue(static (r, v) => r.HAlignRight = v, sourceStyle.HAlignRight, startLoc, endLoc);
                break;
            }

            case nameof(ExcelRangeStyleViewModel.VAlignTop):
            {
                SetRangesPropertyValue(static (r, v) => r.VAlignTop = v, sourceStyle.VAlignTop, startLoc, endLoc);
                break;
            }

            case nameof(ExcelRangeStyleViewModel.VAlignCenter):
            {
                SetRangesPropertyValue(static (r, v) => r.VAlignCenter = v, sourceStyle.VAlignCenter, startLoc, endLoc);
                break;
            }

            case nameof(ExcelRangeStyleViewModel.VAlignBottom):
            {
                SetRangesPropertyValue(static (r, v) => r.VAlignBottom = v, sourceStyle.VAlignBottom, startLoc, endLoc);
                break;
            }

            case nameof(ExcelRangeStyleViewModel.AddAroundBorder):
            {
                SetRangesPropertyValue(static (r, v) => r.AddAroundBorder = v, sourceStyle.AddAroundBorder, startLoc,
                    endLoc);
                break;
            }

            case nameof(ExcelRangeStyleViewModel.AddHorizontalBorder):
            {
                SetRangesPropertyValue(static (r, v) => r.AddHorizontalBorder = v, sourceStyle.AddHorizontalBorder,
                    startLoc, endLoc);
                break;
            }

            case nameof(ExcelRangeStyleViewModel.AddVerticalBorder):
            {
                SetRangesPropertyValue(static (r, v) => r.AddVerticalBorder = v, sourceStyle.AddVerticalBorder,
                    startLoc, endLoc);
                break;
            }

            case nameof(ExcelRangeStyleViewModel.BorderStyle):
            {
                SetRangesPropertyValue(static (r, v) => r.BorderStyle = v, sourceStyle.BorderStyle, startLoc, endLoc);
                break;
            }

            case nameof(ExcelRangeStyleViewModel.Wrap):
            {
                SetRangesPropertyValue(static (r, v) => r.Wrap = v, sourceStyle.Wrap, startLoc, endLoc);
                break;
            }

            case nameof(ExcelRangeStyleViewModel.NumberFormatLocal):
            {
                SetRangesPropertyValue(static (r, v) => r.NumberFormatLocal = v, sourceStyle.NumberFormatLocal,
                    startLoc, endLoc);
                break;
            }
        }
    }


    private void OnGlobalOptionPropertyChanged(object? sender, PropertyChangedEventArgs e)
    {
        if (GlobalStyle.UpdatingInternal)
        {
            return;
        }

        UpdateRangePropertyByCallback(e.PropertyName, GlobalStyle, TableRangeLocations.Section,
            TableRangeLocations.Global);
    }


    private void OnMenuLinkSheetGlobalOptionPropertyChanged(object? sender, PropertyChangedEventArgs e)
    {
        if (MenuLinkSheetGlobalStyle.UpdatingInternal)
        {
            return;
        }

        UpdateRangePropertyByCallback(e.PropertyName, MenuLinkSheetGlobalStyle,
            TableRangeLocations.MenuLinkSheetLabel, TableRangeLocations.MenuLinkSheetGobal);
    }


    private void OnMenuGlobalOptionPropertyChanged(object? sender, PropertyChangedEventArgs e)
    {
        if (MenuGlobalStyle.UpdatingInternal)
        {
            return;
        }

        UpdateRangePropertyByCallback(e.PropertyName, MenuGlobalStyle, TableRangeLocations.MenuBackText,
            TableRangeLocations.MenuGlobal);
    }


    private void OnHyperlinkOptionPropertyChanged(object? sender, PropertyChangedEventArgs e)
    {
        if (HyperlinkStyle.UpdatingInternal || e.PropertyName != nameof(ExcelRangeStyleViewModel.FontWeight))
        {
            return;
        }

        if (HyperlinkStyle.FontWeight == FontWeights.Bold)
        {
            TitleFontWeight = FontWeights.Bold;
        }
        else if (TitleStyle.FontWeight != FontWeights.Bold)
        {
            TitleFontWeight = FontWeights.Normal;
        }
    }


    private void OnTitleStyleOptionPropertyChanged(object? sender, PropertyChangedEventArgs e)
    {
        if (TitleStyle.UpdatingInternal || e.PropertyName != nameof(ExcelRangeStyleViewModel.FontWeight))
        {
            return;
        }

        if (TitleStyle.FontWeight == FontWeights.Bold)
        {
            TitleFontWeight = FontWeights.Bold;
        }
        else if (HyperlinkStyle.FontWeight != FontWeights.Bold)
        {
            TitleFontWeight = FontWeights.Normal;
        }
    }


    [MemberNotNull(nameof(CurrentStyle), nameof(CurrentStyleLabel))]
    public void SetCurrentStyleRange(TableRangeLocations location)
    {
        CurrentStyle = Ranges[(int)location];
        CurrentStyleLabel = $"当前区间：{RangeLocationLabels[(int)location]}";
        IsRangeOptionsEnabled = location < TableRangeLocations.Hyperlink;
        IsFontOptionsEnabled = location != TableRangeLocations.Title &&
                               location != TableRangeLocations.MenuBackText &&
                               location != TableRangeLocations.MenuTableNumber;
    }


    partial void OnSectionFeatureTextChanged(string value)
    {
        if (value.Length > 0)
        {
            SectionStartFeature = value[0].ToString();
        }

        if (value.Length > 1)
        {
            SectionEndFeature = value[1].ToString();
        }
    }


    private void SetInternal(Action setter)
    {
        if (UpdatingInternal)
        {
            return;
        }

        UpdatingInternal = true;
        setter();
        UpdatingInternal = false;
    }


    partial void OnReadSectionChanged(bool value)
    {
        if (!value)
        {
            SetInternal(() => ShowSection = false);
            DisplaySectionStartFeature = SectionStartFeature;
            DisplayTitleSection = "Section";
            DisplaySectionEndFeature = SectionEndFeature;
        }
        else
        {
            DisplaySectionStartFeature = "";
            DisplayTitleSection = "";
            DisplaySectionEndFeature = "";
        }
    }

    partial void OnShowSectionChanged(bool value)
    {
        if (value)
        {
            SetInternal(() => ReadSection = true);
        }
    }


    partial void OnMergeHeaderEmptyRowsChanged(bool value)
    {
        if (value)
        {
            SetInternal(() => RemoveHeaderEmptyRows = false);
        }
    }

    partial void OnRemoveHeaderEmptyRowsChanged(bool value)
    {
        if (value)
        {
            SetInternal(() => MergeHeaderEmptyRows = false);
        }
    }


    partial void OnIsMenuNumberHiddenChanged(bool value)
    {
        SetInternal(() =>
        {
            if (value)
            {
                MenuSheetLabelTextBindingStyle = HyperlinkStyle;
                MenuTableLabelTextBindingStyle = HyperlinkStyle;
            }
            else
            {
                MenuSheetLabelTextBindingStyle = MenuSheetLabelStyle;
                MenuTableLabelTextBindingStyle = MenuTableLabelStyle;
            }
        });
    }


    partial void OnTitleFeatureChanged(string value)
    {
        if (!HideTitleFeature)
        {
            DisplayTitleFeature = value;
        }
    }


    partial void OnHideTitleFeatureChanged(bool value) => DisplayTitleFeature = value ? "" : TitleFeature;


    partial void OnSectionStartFeatureChanged(string value)
    {
        if (!ReadSection)
        {
            DisplaySectionStartFeature = value;
        }
    }


    partial void OnSectionEndFeatureChanged(string value)
    {
        if (!ReadSection)
        {
            DisplaySectionEndFeature = value;
        }
    }


    [RelayCommand]
    private void MergeMenuSection() => IsMenuSectionMerged = true;


    [RelayCommand]
    private void UnMergeMenuSection() => IsMenuSectionMerged = false;


    [RelayCommand]
    private void HideMenuNumber() => IsMenuNumberHidden = true;


    partial void OnShowMultiBaseInOneCellChanged(bool value)
    {
        if (value)
        {
            ShowMenuMultiBase = true;
        }
    }


    public void LoadOption(TableFormatterOptions source, IReportService reportService)
    {
        IntervalRows = source.Table.IntervalRows;
        BaseFeature = source.Table.BaseFeature;
        TitleFeature = source.Table.TitleFeature;
        TableEndFeature = source.Table.EndFeature;
        HideTitleFeature = source.Table.RemoveTitleFeature;
        TitleOffset = source.Table.TitleOffset;
        SectionFeatureText = source.Table.SectionFeature.ToString();
        ReadSection = source.Table.ReadSection;
        ShowSection = source.Table.ShowSection;
        FirstColumnWidth = source.Table.FirstColumnWidth;
        FixedColumnWidth = source.Table.FixedColumnWidth;
        MergeHeader = source.Table.MergeHeader;
        MergeTopLeftCell = source.Table.MergeTopLeftCells;
        MergeHeaderEmptyRows = source.Table.MergeHeaderEmptyRow;
        RemoveHeaderEmptyRows = source.Table.RemoveHeaderEmptyRow;
        RemoveHeaderSpec = source.Table.RemoveHeaderSpec;
        RemoveTailSpec = source.Table.RemoveTailSpec;
        TableNumberFeature = source.Table.TableNumberFeature;
        TableNumberFormat = source.Table.TableNumberFormat;
        CorrectTableNumber = source.Table.CorrectTableNumber;
        SideColorIgnoreEmpty = source.Table.SideColorIgnoreEmpty;
        MaxEmptyRows = source.Table.MaxEmptyRows;

        GlobalStyle.LoadOption(source.Table, reportService);
        HyperlinkStyle.LoadOption(source.Table.HyperlinkStyleOptions, reportService);

        SectionStyle.LoadOption(source.Table.SectionStyleOptions, reportService);
        SectionMemberStyle.LoadOption(source.Table.SectionMemberStyleOptions, reportService);
        TitleStyle.LoadOption(source.Table.TitleStyleOptions, reportService);
        HeaderStyle.LoadOption(source.Table.HeaderStyleOptions, reportService);
        BaseLabelStyle.LoadOption(source.Table.BaseLabelStyleOptions, reportService);
        BaseValueStyle.LoadOption(source.Table.BaseValueStyleOptions, reportService);
        SideStyle.LoadOption(source.Table.SideStyleOptions, reportService);
        InnerTextStyle.LoadOption(source.Table.InnerTextStyleOptions, reportService);
        DataStyle.LoadOption(source.Table.DataStyleOptions, reportService);
        SigColumCharacterStyle.LoadOption(source.Sig.SigMarkRowStyleOptions, reportService);

        // Sig
        MergeSig = source.Sig.Merge;
        SigBoundary = source.Sig.GapBoundary;
        SigBoundaryType = source.Sig.GapBoundaryType;
        HideSigColumnCharacter = source.Sig.HideSigColumnMark;
        HideSigResultCharacter = source.Sig.HideSigCellCharacter;
        SigComparisons.LoadOption(source.Sig.ComparisonMap);
        SigResultStyle.LoadOption(source.Sig.SigResultStyleOptions, reportService);
        UpperCaseSigCharacterStyle.LoadOption(source.Sig.UpperCaseStyleOptions, reportService);
        LowerCaseSigCharacterStyle.LoadOption(source.Sig.LowerCaseStyleOptions, reportService);

        // Menu
        BuildMenu = source.Menu.BuildMenu;
        MenuLinkSheetName = source.Menu.LinkSheetName;
        MenuIndexSheetName = source.Menu.IndexSheetName;
        MenuLinkSheetLabel = source.Menu.LinkSheetLabel;
        IsMenuNumberHidden = source.Menu.HideNumber;
        MenuBackText = source.Menu.BackText;
        ShowSection = source.Menu.ShowSection;
        IsMenuSectionMerged = source.Menu.MergeSection;
        ShowMenuBase = source.Menu.ShowBase;
        ShowMenuMultiBase = source.Menu.ShowMultiBase;
        ShowMultiBaseInOneCell = source.Menu.ShowMultiBaseInOneCell;
        MenuBaseContentFormat = source.Menu.BaseContentFormat;

        MenuLinkSheetLabelStyle.LoadOption(source.Menu.LinkSheetLabelStyleOptions, reportService);
        MenuLinkSheetSheetNameStyle.LoadOption(source.Menu.LinkSheetSheetNameStyleOptions, reportService);
        MenuBackTextStyle.LoadOption(source.Menu.BackStyleOptions, reportService);
        MenuSectionStyle.LoadOption(source.Menu.SectionStyleOptions, reportService);
        MenuSheetLabelStyle.LoadOption(source.Menu.SheetLabelStyleOptions, reportService);
        MenuTableLabelStyle.LoadOption(source.Menu.TableLabelStyleOptions, reportService);
        MenuBaseLabelStyle.LoadOption(source.Menu.BaseStyleOptions, reportService);
        MenuTableNumberStyle.LoadOption(source.Menu.TableNumberStyleOptions, reportService);
    }


    public bool TryWriteOptions(TableFormatterOptions options, IReportService reportService)
    {
        options.Table.IntervalRows = IntervalRows;
        options.Table.BaseFeature = BaseFeature;
        options.Table.TitleFeature = TitleFeature;
        options.Table.EndFeature = TableEndFeature;
        options.Table.RemoveTitleFeature = HideTitleFeature;
        options.Table.TitleOffset = TitleOffset;
        options.Table.SectionFeature = new TableSectionFeature
        {
            Left = SectionStartFeature,
            Right = SectionEndFeature
        };
        options.Table.ReadSection = ReadSection;
        options.Table.ShowSection = ShowSection;
        options.Table.FirstColumnWidth = FirstColumnWidth;
        options.Table.FixedColumnWidth = FixedColumnWidth;
        options.Table.MergeHeader = MergeHeader;
        options.Table.MergeTopLeftCells = MergeTopLeftCell;
        options.Table.MergeHeaderEmptyRow = MergeHeaderEmptyRows;
        options.Table.RemoveHeaderEmptyRow = RemoveHeaderEmptyRows;
        options.Table.RemoveHeaderSpec = RemoveHeaderSpec;
        options.Table.RemoveTailSpec = RemoveTailSpec;
        options.Table.TableNumberFeature = TableNumberFeature;
        options.Table.TableNumberFormat = TableNumberFormat;
        options.Table.CorrectTableNumber = CorrectTableNumber;
        options.Table.SideColorIgnoreEmpty = SideColorIgnoreEmpty;
        options.Table.MaxEmptyRows = MaxEmptyRows;

        GlobalStyle.TryWriteOption(options.Table, reportService);
        HyperlinkStyle.TryWriteOption(options.Table.HyperlinkStyleOptions, reportService);

        SectionStyle.TryWriteOption(options.Table.SectionStyleOptions, reportService);
        SectionMemberStyle.TryWriteOption(options.Table.SectionMemberStyleOptions, reportService);
        TitleStyle.TryWriteOption(options.Table.TitleStyleOptions, reportService);
        HeaderStyle.TryWriteOption(options.Table.HeaderStyleOptions, reportService);
        BaseLabelStyle.TryWriteOption(options.Table.BaseLabelStyleOptions, reportService);
        BaseValueStyle.TryWriteOption(options.Table.BaseValueStyleOptions, reportService);
        SideStyle.TryWriteOption(options.Table.SideStyleOptions, reportService);
        InnerTextStyle.TryWriteOption(options.Table.InnerTextStyleOptions, reportService);
        DataStyle.TryWriteOption(options.Table.DataStyleOptions, reportService);
        SigColumCharacterStyle.TryWriteOption(options.Sig.SigMarkRowStyleOptions, reportService);

        // Sig
        options.Sig.Merge = MergeSig;
        options.Sig.GapBoundary = SigBoundary;
        options.Sig.GapBoundaryType = SigBoundaryType;
        options.Sig.HideSigColumnMark = HideSigColumnCharacter;
        options.Sig.HideSigCellCharacter = HideSigResultCharacter;
        SigComparisons.TryWriteOption(options.Sig.ComparisonMap, reportService);
        SigResultStyle.TryWriteOption(options.Sig.SigResultStyleOptions, reportService);
        UpperCaseSigCharacterStyle.TryWriteOption(options.Sig.UpperCaseStyleOptions, reportService);
        LowerCaseSigCharacterStyle.TryWriteOption(options.Sig.LowerCaseStyleOptions, reportService);

        // Menu
        options.Menu.BuildMenu = BuildMenu;
        options.Menu.LinkSheetName = MenuLinkSheetName;
        options.Menu.IndexSheetName = MenuIndexSheetName;
        options.Menu.LinkSheetLabel = MenuLinkSheetLabel;
        options.Menu.HideNumber = IsMenuNumberHidden;
        options.Menu.BackText = MenuBackText;
        options.Menu.ShowSection = ShowSection;
        options.Menu.MergeSection = IsMenuSectionMerged;
        options.Menu.ShowBase = ShowMenuBase;
        options.Menu.ShowMultiBase = ShowMenuMultiBase;
        options.Menu.ShowMultiBaseInOneCell = ShowMultiBaseInOneCell;
        options.Menu.BaseContentFormat = MenuBaseContentFormat;

        MenuLinkSheetLabelStyle.TryWriteOption(options.Menu.LinkSheetLabelStyleOptions, reportService);
        MenuLinkSheetSheetNameStyle.TryWriteOption(options.Menu.LinkSheetSheetNameStyleOptions, reportService);
        MenuBackTextStyle.TryWriteOption(options.Menu.BackStyleOptions, reportService);
        MenuSectionStyle.TryWriteOption(options.Menu.SectionStyleOptions, reportService);
        MenuSheetLabelStyle.TryWriteOption(options.Menu.SheetLabelStyleOptions, reportService);
        MenuTableLabelStyle.TryWriteOption(options.Menu.TableLabelStyleOptions, reportService);
        MenuBaseLabelStyle.TryWriteOption(options.Menu.BaseStyleOptions, reportService);
        MenuTableNumberStyle.TryWriteOption(options.Menu.TableNumberStyleOptions, reportService);

        return true;
    }


    #region Sig Characters

    [ObservableProperty]
    public partial string SigCharUpperA { get; set; } = "A";

    [ObservableProperty]
    public partial string SigCharUpperB { get; set; } = "B";

    [ObservableProperty]
    public partial string SigCharLowerA { get; set; } = "a";

    [ObservableProperty]
    public partial string SigCharLowerB { get; set; } = "b";

    [ObservableProperty]
    public partial string SigCharLowerC { get; set; } = "c";


    private void SetSigCharVisible(bool visible)
    {
        SigCharUpperA = visible ? "A" : "";
        SigCharUpperB = visible ? "B" : "";
        SigCharLowerA = visible ? "a" : "";
        SigCharLowerB = visible ? "b" : "";
        SigCharLowerC = visible ? "c" : "";
    }


    [ObservableProperty]
    public partial string SigCharUpperAInCell { get; set; } = "";

    [ObservableProperty]
    public partial string SigCharUpperBInCell { get; set; } = "";

    [ObservableProperty]
    public partial string SigCharLowerAInCell { get; set; } = "";

    [ObservableProperty]
    public partial string SigCharLowerBInCell { get; set; } = "";

    [ObservableProperty]
    public partial string SigCharLowerCInCell { get; set; } = "";


    private void SetSigCharInCellVisible(bool visible)
    {
        SigCharUpperAInCell = visible ? "A" : "";
        SigCharUpperBInCell = visible ? "B" : "";
        SigCharLowerAInCell = visible ? "a" : "";
        SigCharLowerBInCell = visible ? "b" : "";
        SigCharLowerCInCell = visible ? "c" : "";
    }


    partial void OnMergeSigChanged(bool value)
    {
        SetSigCharInCellVisible(value);
        SetSigCharVisible(!value);
    }

    #endregion
}

public enum TableRangeLocations
{
    [Description("分组")]
    Section,

    [Description("表头")]
    Header,

    [Description("分组成员")]
    SectionMember,

    [Description("标题")]
    Title,

    [Description("基数描述")]
    BaseLabel,

    [Description("基数值")]
    BaseValue,

    [Description("表侧")]
    Side,

    [Description("表侧中间文本")]
    InnerText,

    [Description("数据")]
    Data,

    [Description("显著性列字母")]
    SigColumnCharacter,

    [Description("显著性结果")]
    SigResult,

    [Description("全局")]
    Global,

    [Description("Sheet索引页描述")]
    MenuLinkSheetLabel,

    [Description("Sheet索引页Sheet名")]
    MenuLinkSheetSheetName,

    [Description("Sheet索引页全局")]
    MenuLinkSheetGobal,

    [Description("表格索引页返回链接")]
    MenuBackText,

    [Description("表格索引页表格计数")]
    MenuTableNumber,

    [Description("表格索引页分组")]
    MenuSection,

    [Description("表格索引页基数描述")]
    MenuBaseLabel,

    [Description("表格索引页Sheet名")]
    MenuSheetLabel,

    [Description("表格索引页表格名")]
    MenuTableLabel,

    [Description("表格索引页全局")]
    MenuGlobal,

    [Description("超链接文本")]
    Hyperlink,

    [Description("显著性小写字母")]
    LowerCaseSigCharacter,

    [Description("显著性大写字母")]
    UpperCaseSigCharacter,
    StylesCount
}